#ifndef PF_PfMap_H
#define PF_PfMap_H

#include <vector>

struct PfVec2
{
	int x,y;

	PfVec2() {}
	PfVec2(int x, int y) : x(x), y(y) {}

	operator const int * () const { return &x; }
	operator int * () { return &x; }

	PfVec2 operator+(const PfVec2 & v) const { return PfVec2(x+v.x,y+v.y); }
	PfVec2 operator-(const PfVec2 & v) const { return PfVec2(x-v.x,y-v.y); }
};

struct PfSegment
{
	PfVec2 v0,v1;

	PfSegment() {}
	PfSegment(const PfVec2 & v0, const PfVec2 & v1) : v0(v0), v1(v1) {}
};

typedef unsigned char Tile;

#define TILE_SPACE			253
#define TILE_BORDER			254
#define TILE_OBSTRUCTION	255

struct PfMap
{
	struct Border
	{
		PfVec2 start,end;
		PfVec2 center;
		Tile regionA;
		Tile regionB;
	};

	struct Region
	{
		std::vector<size_t> borderVertices;
	};

	struct Edge
	{
		bool	connected;
		size_t	successor;
		float	cost;
	};

	std::vector<Tile> tiles;
	int width;
	int height;
	int wshift;

	int numRegions;
	std::vector<Border> borders;

	std::vector<Region> regions;

	std::vector<Edge> edges;

	Border & GetBorder(size_t border)
	{
		return borders[border];
	}

	Region & GetRegion(Tile region)
	{
		return regions[region];
	}

	Edge & GetEdge(size_t borderVertex0, size_t borderVertex1)
	{
		return edges[borderVertex0*borders.size()+borderVertex1];
	}

	Tile At(int x, int y) const { return tiles[(y<<wshift)|x]; }
	Tile & At(int x, int y) { return tiles[(y<<wshift)|x]; }

	Tile operator()(int x, int y) const { return At(x,y); }
	Tile & operator()(int x, int y) { return At(x,y); }

	operator const Tile * () const { return &tiles.front(); }
	operator Tile * () { return &tiles.front(); }

	bool Load(const char * filename);

	void MakeRegions(const std::vector<PfSegment> & borders);

	void SaveGraph(const char * filename);
private:
	void SetLine(const PfSegment & line);
	void FloodFill(int x, int y, Tile tile);
	void GenBorder(size_t index);
	void ConnectEdge(size_t i, size_t j);
};

#endif